import xmlFormat from 'xml-formatter';
import { EdgeConfig, NodeConfig,Point } from '@logicflow/core';
import { BpmnConfigMap } from '../constant';

const convertGraphData2Xml = (graphData:any)=>{
  console.log('convertXml graphData',graphData);
  const props = graphData.props as any;
  const nodes = graphData.nodes as NodeConfig[];
  const edges = graphData.edges as EdgeConfig[];

  const bpmnDoc = new Document();
  const definitionsElement = bpmnDoc.appendChild(bpmnDoc.createElement('definitions'));
  definitionsElement.setAttribute("xmlns","http://www.omg.org/spec/BPMN/20100524/MODEL");
  definitionsElement.setAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
  definitionsElement.setAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
  definitionsElement.setAttribute("xmlns:flowable","http://flowable.org/bpmn");
  definitionsElement.setAttribute("xmlns:bpmndi","http://www.omg.org/spec/BPMN/20100524/DI");
  definitionsElement.setAttribute("xmlns:omgdc","http://www.omg.org/spec/DD/20100524/DC");
  definitionsElement.setAttribute("xmlns:omgdi","http://www.omg.org/spec/DD/20100524/DI");
  definitionsElement.setAttribute("typeLanguage","http://www.w3.org/2001/XMLSchema");
  definitionsElement.setAttribute("expressionLanguage","http://www.w3.org/1999/XPath");
  definitionsElement.setAttribute("targetNamespace","http://www.flowable.org/processdef");
  
  const processElement = definitionsElement.appendChild(bpmnDoc.createElement('process'));
  processElement.setAttribute('id',props.process.id);
  processElement.setAttribute('name',props.process.name);
  processElement.setAttribute('isExecutable',props.process.isExecutable);
  processElement.setAttribute('flowable:candidateStarterUsers',props.process.candidateStarterUsers);
  processElement.setAttribute('flowable:candidateStarterGroups',props.process.candidateStarterGroups);
  if(props.process.documentation){
    const processDocumentation = processElement.appendChild(bpmnDoc.createElement('documentation'));
    processDocumentation.append(props.process.documentation);
  }

  const BPMNDiagramElement = definitionsElement.appendChild(bpmnDoc.createElement('bpmndi:BPMNDiagram'));
  BPMNDiagramElement.setAttribute('id',`BPMNDiagram_${props.process.id}`);

  const BPMNPlaneElement = BPMNDiagramElement.appendChild(bpmnDoc.createElement('bpmndi:BPMNPlane'));
  BPMNPlaneElement.setAttribute('id',`BPMNPlane_${props.process.id}`);
  BPMNPlaneElement.setAttribute('bpmnElement',props.process.id);
  
  for(let nodeConfig of nodes){
    const bpmnNodeElement = processElement.appendChild(bpmnDoc.createElement(nodeConfig.type));
    bpmnNodeElement.setAttribute('id',nodeConfig.id as string);
    bpmnNodeElement.setAttribute('name',typeof(nodeConfig.text)==='object'?nodeConfig.text.value:nodeConfig.text as string);
    if(nodeConfig.properties?.documentation){
      const documentation = bpmnNodeElement.appendChild(bpmnDoc.createElement('documentation'));
      documentation.append(nodeConfig.properties.documentation as string);
    }
    // TODO
    const bpmnShapeElement = BPMNPlaneElement.appendChild(bpmnDoc.createElement('bpmndi:BPMNShape'));
    bpmnShapeElement.setAttribute('id',`BPMNShape_${nodeConfig.id as string}`);
    bpmnShapeElement.setAttribute('bpmnElement',nodeConfig.id as string);
    const bpmnBoundsElement = bpmnShapeElement.appendChild(bpmnDoc.createElement('omgdc:Bounds'));
    const height = BpmnConfigMap.get(nodeConfig.type).height;
    const width = BpmnConfigMap.get(nodeConfig.type).width;
    bpmnBoundsElement.setAttribute('height',BpmnConfigMap.get(nodeConfig.type).height);
    bpmnBoundsElement.setAttribute('width',BpmnConfigMap.get(nodeConfig.type).width);
    bpmnBoundsElement.setAttribute('x',''+(nodeConfig.x - width/2));
    bpmnBoundsElement.setAttribute('y',''+(nodeConfig.y - height/2));
    
  }
  for(let edgeConfig of edges){
    const bpmnFlowElement = processElement.appendChild(bpmnDoc.createElement(edgeConfig.type as string));
    bpmnFlowElement.setAttribute('id',edgeConfig.id as string);
    bpmnFlowElement.setAttribute('name',typeof(edgeConfig.text)==='object'?edgeConfig.text.value:edgeConfig.text as string);
    bpmnFlowElement.setAttribute('sourceRef',edgeConfig.sourceNodeId);
    bpmnFlowElement.setAttribute('targetRef',edgeConfig.targetNodeId);
    if(edgeConfig.properties?.documentation){
      const documentation = bpmnFlowElement.appendChild(bpmnDoc.createElement('documentation'));
      documentation.append(edgeConfig.properties.documentation as string);
    }
    // TODO
    const bpmnEdgeElement = BPMNPlaneElement.appendChild(bpmnDoc.createElement('bpmndi:BPMNEdge'));
    bpmnEdgeElement.setAttribute('id',`BPMNEdge_${edgeConfig.id as string}`);
    bpmnEdgeElement.setAttribute('bpmnElement',edgeConfig.id as string);
    edgeConfig.pointsList && edgeConfig.pointsList.forEach((point)=>{
      const bpmnWaypointElement = bpmnEdgeElement.appendChild(bpmnDoc.createElement('omgdi:waypoint'));
      bpmnWaypointElement.setAttribute('x',''+point.x);
      bpmnWaypointElement.setAttribute('y',''+point.y);
    });
    

  }

  const bpmnXml = xmlFormat('<?xml version="1.0" encoding="UTF-8"?>'+bpmnDoc.documentElement.outerHTML,{indentation: '  '});
  console.log('convertXml bpmnXml',bpmnXml);
  return bpmnXml;
}
export default convertGraphData2Xml;